<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.2" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="计算机,pthread,线程同步,互斥量,读写锁,条件变量,信号量," />





  <link rel="alternate" href="/atom.xml" title="学不可以已" type="application/atom+xml" />




  <link rel="shortcut icon" type="image/x-icon" href="/uploads/favicon.ico?v=5.1.2" />






<meta name="description" content="线程为什么要同步 当多个控制线程共享相同的内存时，需要确保每个线程看到一致的视图，如果每个线程使用的变量都是其他线程不会读取和修改的，那么就不存在一致性问题，同样，如果变量是只读的，多个线程同时读取该变量也不会有一致性问题，但是，当一个线程可以修改的变量，其他的线程也可以读取或者修改的时候，我们就需要对这些线程进行同步，确保它们在访问变量的存储内容时不会访问到无效的值。  互斥量 可以使用pthr">
<meta name="keywords" content="计算机,pthread,线程同步,互斥量,读写锁,条件变量,信号量">
<meta property="og:type" content="article">
<meta property="og:title" content="多线程同步">
<meta property="og:url" content="http://eregg.com/2016/11/22/多线程同步/index.html">
<meta property="og:site_name" content="学不可以已">
<meta property="og:description" content="线程为什么要同步 当多个控制线程共享相同的内存时，需要确保每个线程看到一致的视图，如果每个线程使用的变量都是其他线程不会读取和修改的，那么就不存在一致性问题，同样，如果变量是只读的，多个线程同时读取该变量也不会有一致性问题，但是，当一个线程可以修改的变量，其他的线程也可以读取或者修改的时候，我们就需要对这些线程进行同步，确保它们在访问变量的存储内容时不会访问到无效的值。  互斥量 可以使用pthr">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2017-09-21T18:14:58.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="多线程同步">
<meta name="twitter:description" content="线程为什么要同步 当多个控制线程共享相同的内存时，需要确保每个线程看到一致的视图，如果每个线程使用的变量都是其他线程不会读取和修改的，那么就不存在一致性问题，同样，如果变量是只读的，多个线程同时读取该变量也不会有一致性问题，但是，当一个线程可以修改的变量，其他的线程也可以读取或者修改的时候，我们就需要对这些线程进行同步，确保它们在访问变量的存储内容时不会访问到无效的值。  互斥量 可以使用pthr">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    version: '5.1.2',
    sidebar: {"position":"left","display":"post","offset":12,"offset_float":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://eregg.com/2016/11/22/多线程同步/"/>





  <title>多线程同步 | 学不可以已</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?5f1629a8f7280df347a90a49b56b2b49";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">学不可以已</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">青，取之于蓝，而青于蓝</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/多线程同步/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="eregg">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="学不可以已">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">多线程同步</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:39:37+08:00">
                2016-11-22
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h3 id="线程为什么要同步"><a href="#线程为什么要同步" class="headerlink" title="线程为什么要同步"></a><a href="#线程为什么要同步" title="线程为什么要同步"></a>线程为什么要同步</h3><blockquote>
<p>当多个控制线程共享相同的内存时，需要确保每个线程看到一致的视图，如果每个线程使用的变量都是其他线程不会读取和修改的，那么就不存在一致性问题，同样，如果变量是只读的，多个线程同时读取该变量也不会有一致性问题，但是，<strong>当一个线程可以修改的变量，其他的线程也可以读取或者修改的时候，我们就需要对这些线程进行同步，确保它们在访问变量的存储内容时不会访问到无效的值</strong>。</p>
</blockquote>
<h3 id="互斥量"><a href="#互斥量" class="headerlink" title="互斥量"></a><a href="#互斥量" title="互斥量"></a>互斥量</h3><blockquote>
<p>可以使用pthread的互斥接口来保护数据，确保在同一时间只有一个线程可以访问共享数据，<strong>互斥量（mutex）从本质上说就是一把锁</strong>，在访问共享资源前对互斥量进行设置（加锁），在访问完成后释放（解锁）互斥量，对互斥量进行加锁以后，任何其他试图再次对互斥量进行加锁的线程都会被阻塞直到当前线程释放该互斥锁，如果释放互斥量时有一个以上的线程阻塞，那么所有该锁上的线程都会被变成可运行状态，第一个被运行的线程就可以对互斥量加锁，其他线程就会看到互斥量依然是锁着的，只能回去再次等待它重新变为可用。在这种情况下每次只有一个线程可以向前执行。</p>
</blockquote>
<h4 id="临界区（Critical-Section）"><a href="#临界区（Critical-Section）" class="headerlink" title="临界区（Critical Section）"></a><a href="#临界区（Critical-Section）" title="临界区（Critical Section）"></a>临界区（Critical Section）</h4><blockquote>
<p>保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共<br>享资源进行访问。如果有多个线程试图同时访问临界区，那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起，并一直持续到进入临界区的线程离开。临界区在被释放后，其他线程可以继续抢占，并以此达到用原子方式操作共享资源的目的。</p>
</blockquote>
<h4 id="临界区的选定"><a href="#临界区的选定" class="headerlink" title="临界区的选定"></a><a href="#临界区的选定" title="临界区的选定"></a>临界区的选定</h4><blockquote>
<p>临界区的选定因尽可能小，如果选定太大会影响程序的并行处理性能。</p>
</blockquote>
<h4 id="互斥量（mutex）原语"><a href="#互斥量（mutex）原语" class="headerlink" title="互斥量（mutex）原语"></a><a href="#互斥量（mutex）原语" title="互斥量（mutex）原语"></a>互斥量（mutex）原语</h4><h5 id="pthread-mutex-t"><a href="#pthread-mutex-t" class="headerlink" title="pthread_mutex_t"></a><a href="#pthread-mutex-t" title="pthread_mutex_t"></a>pthread_mutex_t</h5><blockquote>
<p><strong>互斥量使用pthread_mutex_t数据类型表示的</strong>。在使用互斥变量以前，必须首先对它进行初始化，<strong>_可以把他设置为常量PTHREAD_MUTEX<em>INITIALIZER（只适用于静态分配的互斥量）</em></strong>，也可以<strong>通过调用pthread_mutex_init函数进行初始化</strong>。如果动态分配互斥量（例如，通过调malloc函数），在释放内存前需要调用pthread_mutex_destroy。</p>
<h5 id="pthread-mutex-init"><a href="#pthread-mutex-init" class="headerlink" title="pthread_mutex_init"></a><a href="#pthread-mutex-init" title="pthread_mutex_init"></a>pthread_mutex_init</h5><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_init</span><span class="params">(<span class="keyword">pthread_mutex_t</span> <em><span class="keyword">restrict</span> mutex,</em></span></span></div><div class="line">              <span class="keyword">const</span> <span class="keyword">pthread_mutexattr_t</span> <span class="keyword">restrict</span> attr);</div><div class="line"><span class="keyword">pthread_mutex_t</span> mutex = PTHREAD_MUTEX_INITIALIZER;</div><div class="line">返回值：成功返回<span class="number">0</span>，否则，返回错误编号。</div></pre></td></tr></table></figure>

<p>需要默认的属性初始化互斥量，只需要把attr设为NULL。</p>
</blockquote>
<h5 id="pthread-mutex-lock"><a href="#pthread-mutex-lock" class="headerlink" title="pthread_mutex_lock"></a><a href="#pthread-mutex-lock" title="pthread_mutex_lock"></a>pthread_mutex_lock</h5><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_lock</span><span class="params">(<span class="keyword">pthread_mutex_t</span> <em>mutex)</em></span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_trylock</span><span class="params">(<span class="keyword">pthread_mutex_t</span> mutex)</span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_unlock</span><span class="params">(<span class="keyword">pthread_mutex_t</span> <em>mutex)</em></span></span>;</div><div class="line">返回值：成功返回<span class="number">0</span>，否则，返回错误编号。</div></pre></td></tr></table></figure><br>&gt; 对互斥量进行加锁，需要调用pthread_mutex_lock。如果互斥量已经上锁，调用线程将阻塞直到互斥量被解锁，对互斥量解锁，需要调用pthread_mutex_unlock。<br>&gt;<br>&gt; ##### <a href="#pthread-mutex-unlock" title="pthread_mutex_unlock"></a>pthread_mutex_unlock<br>&gt;<br>&gt; ##### <a href="#pthread-mutex-destroy" title="pthread_mutex_destroy"></a>pthread_mutex<em>destroy<br><br>### <a href="#死锁" title="死锁"></a>死锁<br>&gt; 如果一个线程试图对同一个互斥量加锁两次，那么他自身就会陷入一种死锁状态，但是使用互斥量时还有其他不太明显的方式也会产生死锁。例如，程序中有一个以上的互斥量时，如果一个线程在持有第一个互斥量时，并且试图锁住第二个互斥量时处于阻塞状态，<br>&gt; （此时第一个互斥量也一直被持有），此时第二个持有第二个互斥量的线程，也在试图获取第一个互斥量时，死锁就产生了，因为两个线程都在互相请求另一个线程拥有的资源，所以这两个线程都无法前进，于是就产生死锁。<br><br>### <a href="#读写锁" title="读写锁"></a>读写锁<br>&gt; 读写锁（reader-writer lock）与互斥量类似，不过读写锁允许更高的并发性，**</em>读共享，写独占_**<br><br>#### <a href="#读写锁原语" title="读写锁原语"></a>读写锁原语<br><br>##### <a href="#pthread-rwlock-t" title="pthread_rwlock_t"></a>pthread_rwlock_t<br>&gt; 读写锁类型<br><br>##### <a href="#pthread-rwlock-init" title="pthread_rwlock_init"></a>pthread_rwlock_init<br><br>##### <a href="#pthread-rwlock-destroy" title="pthread_rwlock_destroy"></a>pthread_rwlock_destroy<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_init</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> <span class="keyword">restrict</span> rwlock,</span></span></div><div class="line">      <span class="keyword">const</span> <span class="keyword">pthread_rwlockattr_t</span> <em><span class="keyword">restrict</span> attr);</em></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_destroy</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> rwlock)</span></span>;</div><div class="line">两个函数返回值：若成功，返回<span class="number">0</span>；否则，返回错误编号</div></pre></td></tr></table></figure><br>&gt; 读写锁通过调用<strong>_pthread_rwlock<em>init</em></strong>进行初始化，如果希望读写锁有默认属性，可以传一个NULL指针给attr<br>&gt;<br>&gt; 在释放读写锁占用的内存之前，需要调用<strong>_pthread_rwlock<em>destroy</em></strong>做清理工作， 如果<strong>_pthread_rwlock<em>init</em></strong>为读写锁分配了资源，<strong>_pthread_rwlock<em>destroy</em></strong>将释放这些资源。<br><br>##### <a href="#pthread-rwlock-rdlock" title="pthread_rwlock_rdlock"></a>pthread_rwlock_rdlock<br><br>##### <a href="#pthread-rwlock-wrlock" title="pthread_rwlock_wrlock"></a>pthread_rwlock_wrlock<br><br>##### <a href="#pthread-rwlock-tryrdlock" title="pthread_rwlock_tryrdlock"></a>pthread_rwlock_tryrdlock<br><br>##### <a href="#pthread-rwlock-trywrlock" title="pthread_rwlock_trywrlock"></a>pthread_rwlock_trywrlock<br><br>##### <a href="#pthread-rwlock-unlock" title="pthread_rwlock_unlock"></a>pthread_rwlock_unlock<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_rdlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> <em>rwlock)</em></span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_wrlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> rwlock)</span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_tryrdlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> <em>rwlock)</em></span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_trywrlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> rwlock)</span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_unlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> <em>rwlock)</em></span></span>;</div><div class="line">所有函数返回值：若成功，返回<span class="number">0</span>；否则，返回错误编号</div></pre></td></tr></table></figure><br>&gt; 要在读模式下锁定读写锁，需要调用<strong>_pthread_rwlock<em>rdlock</em></strong>。要在模式下锁定读写锁，需要调用<strong>_pthread_rwlock<em>wrlock</em></strong>。不管以何种方式锁定读写锁，都可以调用<strong>_pthread_rwlock<em>unlock</em></strong>进行解锁。<br>&gt;<br>&gt; <strong>_pthread_rwlock_tryrdlock，pthread_rwlock<em>trywrlock</em></strong>，非阻塞获得锁<br><br>### <a href="#条件变量" title="条件变量"></a>条件变量

   互斥量的存在问题：<br>  互斥量是线程程序必需的工具，但它们并非万能的。例如，<strong><em>如果线程正在等待共享数据内某个条件出现，那会发生什么呢？它可以重复对互斥对象锁定和解锁，每次都会检查共享数据结构，以查找某个值。但这是在浪费时间和资源，而且这种繁忙查询的效率非常低</em></strong>。<br>  在每次检查之间，可以让调用线程短暂地进入睡眠，比如睡眠三秒钟，但是因此线程代码就无法最快作出响应。真正需要的是这样一种方法：当线程在等待满足某些条件时使线程进入睡眠状态。一旦条件满足，就唤醒因等待满足特定条件而睡眠的线程。如果能够做到这一点，线程代码将是非常高效的，并且不会占用宝贵的互斥对象锁。这正是 POSIX 条件变量能做的事！<br><br><em>   条件变量:<br>  条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足，它常和互斥锁一起使用。使用时，<strong><em>条件变量被用来阻塞一个线程，当条件不满足时，线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量，它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足</em></strong>。

</em>   条件变量是线程可用的另一种同步机制，条件变量给多线程提供了一个会和的场所，<strong><em>条件变量与互斥量一起使用时，允许线程以无竞争的方式等待特定条件的发生</em></strong>。<br><br>#### <a href="#条件变量原语" title="条件变量原语"></a>条件变量原语<br><br>##### <a href="#pthread-cond-t" title="pthread_cond_t"></a>pthread_cond_t<br>&gt; 条件变量类型<br><br>##### <a href="#pthread-cond-init" title="pthread_cond_init"></a>pthread_cond_init<br><br>##### <a href="#pthread-cond-destroy" title="pthread_cond_destroy"></a>pthread_cond_destroy<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">pthread_cond_t</span> cond = PTHREAD_COND_INITIALIZER; <span class="comment">//静态初始化</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_init</span><span class="params">(<span class="keyword">pthread_cond_t</span> <em><span class="keyword">restrict</span> cond,</em></span></span></div><div class="line">      <span class="keyword">const</span> <span class="keyword">pthread_condattr_t</span> <span class="keyword">restrict</span> attr);</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_destroy</span><span class="params">(<span class="keyword">pthread_cond_t</span> <em>cond)</em></span></span>;</div><div class="line">两个函数返回值：若成功，返回<span class="number">0</span>；否则，返回错误编号</div></pre></td></tr></table></figure><br>&gt; 在使用条件变量之前，必须先对它进行初始化。由pthread_cond_t数据类型表示的条件变量可以用两种方式进行初始化，可以把常量PTHREAD_COND_INITIALIZER赋给静态分配的条件变量，但是如果条件变量是动态分配的就需要使用pthread_cond_init函数来对它进行初始化。在释放条件变量底层的内存空间之前，可以使用pthread_cond_destroy函数对条件变量进行反初始化。<br><br>##### <a href="#pthread-cond-wait" title="pthread_cond_wait"></a>pthread_cond_wait<br><br>##### <a href="#pthread-cond-timedwait" title="pthread_cond_timedwait"></a>pthread_cond_timedwait<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_wait</span><span class="params">(<span class="keyword">pthread_cond_t</span> <span class="keyword">restrict</span> cond,</span></span></div><div class="line">      <span class="keyword">pthread_mutex_t</span> <em><span class="keyword">restrict</span> mutex);</em></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_timedwait</span><span class="params">(<span class="keyword">pthread_cond_t</span> <span class="keyword">restrict</span> cond,</span></span></div><div class="line">              <span class="keyword">pthread_mutex_t</span> <em><span class="keyword">restrict</span> mutex,</em></div><div class="line">              <span class="keyword">const</span> <span class="keyword">struct</span> timespec <span class="keyword">restrict</span> abstime);</div><div class="line">两个函数返回值：若成功，返回<span class="number">0</span>；否则，返回错误编号</div></pre></td></tr></table></figure><br>&gt; 传递给pthread_cond<em>wait的互斥量对条件进行保护。**</em>调用者把锁住的互斥量传给函数，函数然后自动把调用线程放到等待条件的线程列表上，对互斥量解锁。这就关闭了条件检查和线程进入睡眠状态等待条件改变这两个操作之间的时间同道，这样线程就不会错过条件的任何变化，pthread_cond<em>wait返回时，互斥量再次被锁住</em><strong>。<br>&gt;<br>&gt; pthread_cond_timedwait函数与pthread_cond_wait函数类似，只是多了一个超时，它是通过timespec结构指定的。<br><br>##### <a href="#pthread-cond-signal" title="pthread_cond_signal"></a>pthread_cond_signal<br><br>##### <a href="#pthread-cond-broadcast" title="pthread_cond_broadcast"></a>pthread_cond_broadcast<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_signal</span><span class="params">(<span class="keyword">pthread_cond_t</span> <em>cond)</em></span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_broadcast</span><span class="params">(<span class="keyword">pthread_cond_t</span> cond)</span></span>;</div><div class="line">两个函数返回值：若成功，返回<span class="number">0</span>；否则，返回错误编号</div></pre></td></tr></table></figure><br>&gt; </strong>_pthread_cond_signal函数至少能唤醒一个等待该条件的线程，pthread_cond<em>broadcast函数则能唤醒等待该条件的所有线程。</em><em>*<br>&gt; 在调用pthread_cond_signal或者pthread_cond_broadcast时，我们说这是在给线程或者条件发信号，必须注意，一定要在改变条件状态以后再给线程发信号。<br><br>### <a href="#信号量" title="信号量"></a>信号量<br><br>### <a href="#进程间锁" title="进程间锁"></a>进程间锁<br><br>### <a href="#实例一（互斥量锁）" title="实例一（互斥量锁）"></a>实例一（互斥量锁）<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;pthread.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> NLOOP 5000</span></div><div class="line"><span class="comment">//定义锁</span></div><div class="line"><span class="keyword">pthread_mutex_t</span> lock;</div><div class="line"></div><div class="line"><span class="keyword">int</span> counter;</div><div class="line"><span class="function"><span class="keyword">void</span></span></div></pre></td></tr></table></figure></em> <span class="title">doit</span><span class="params">(<span class="keyword">void</span> *argv)</span>&#123;<div class="line">    <span class="keyword">int</span> i, val;</div><div class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; NLOOP; i++)&#123;</div><div class="line">        <span class="comment">//获取互斥锁,如果锁被其他线程持有，则阻塞等待。</span></div><div class="line">        pthread_mutex_lock(&amp;lock);</div><div class="line">        val = counter;</div><div class="line">        <span class="built_in">printf</span>(<span class="string">“%x: %d\n”</span>, pthread_self(), val+<span class="number">1</span>);</div><div class="line">        counter = val+<span class="number">1</span>;</div><div class="line">        <span class="comment">//释放互斥锁，以便其他线程持有</span></div><div class="line">        pthread_mutex_unlock(&amp;lock);</div><div class="line">    &#125;   </div><div class="line">    <span class="keyword">return</span> <span class="literal">NULL</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</div><div class="line">    <span class="comment">//初始化互斥锁</span></div><div class="line">    pthread_mutex_init(&amp;lock, <span class="literal">NULL</span>);</div><div class="line">    <span class="keyword">pthread_t</span> tidA, tidB;</div><div class="line">    pthread_create(&amp;tidA, <span class="literal">NULL</span>, &amp;doit, <span class="literal">NULL</span>);</div><div class="line">    pthread_create(&amp;tidB, <span class="literal">NULL</span>, &amp;doit, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line">    pthread_join(tidA, <span class="literal">NULL</span>);</div><div class="line">    pthread_join(tidB, <span class="literal">NULL</span>);</div><div class="line">    <span class="comment">//销毁锁</span></div><div class="line">    pthread_mutex_destroy(&amp;lock);</div><div class="line"></div><div class="line">    <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">&#125;</div>

<h3 id="实例二（死锁）"><a href="#实例二（死锁）" class="headerlink" title="实例二（死锁）"></a><a href="#实例二（死锁）" title="实例二（死锁）"></a>实例二（死锁）</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;pthread.h&gt;</span></span></div><div class="line"></div><div class="line"><span class="comment">//定义两个互斥量锁</span></div><div class="line"><span class="keyword">pthread_mutex_t</span> lockA;</div><div class="line"><span class="keyword">pthread_mutex_t</span> lockB;</div><div class="line"></div><div class="line"><span class="keyword">int</span> a, b;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">pthread_fun1</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>&#123;</div><div class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</div><div class="line">        <span class="comment">//获取锁A</span></div><div class="line">        <span class="built_in">printf</span>(<span class="string">“获取lockA\n”</span>);</div><div class="line">        pthread_mutex_lock(&amp;lockA);</div><div class="line">        a++;</div><div class="line">        <span class="comment">//获取锁B</span></div><div class="line">        <span class="built_in">printf</span>(<span class="string">“获取lockB\n”</span>);</div><div class="line">        pthread_mutex_lock(&amp;lockB);</div><div class="line">        b++;</div><div class="line">        <span class="comment">//释放锁B</span></div><div class="line">        pthread_mutex_unlock(&amp;lockB);</div><div class="line">        <span class="comment">//释放锁A</span></div><div class="line">        pthread_mutex_unlock(&amp;lockA);</div><div class="line">        <span class="built_in">printf</span>(<span class="string">“%x a=%d b=%d\n”</span>, pthread_self(), a, b); </div><div class="line">    &#125;   </div><div class="line"></div><div class="line">    <span class="keyword">return</span> <span class="literal">NULL</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">pthread_fun2</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>&#123;</div><div class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</div><div class="line">        <span class="comment">//获取锁B</span></div><div class="line">        <span class="built_in">printf</span>(<span class="string">“获取lockB\n”</span>);</div><div class="line">        pthread_mutex_lock(&amp;lockB);</div><div class="line">        a++;</div><div class="line">        <span class="comment">//获取锁A</span></div><div class="line">        <span class="built_in">printf</span>(<span class="string">“获取lockA\n”</span>);</div><div class="line">        pthread_mutex_lock(&amp;lockA);</div><div class="line">        b++;</div><div class="line">        <span class="comment">//释放锁A</span></div><div class="line">        pthread_mutex_unlock(&amp;lockA);</div><div class="line">        <span class="comment">//释放锁B</span></div><div class="line">        pthread_mutex_unlock(&amp;lockB);</div><div class="line">        <span class="built_in">printf</span>(<span class="string">“%x a=%d b=%d\n”</span>, pthread_self(), a, b);</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="keyword">return</span> <span class="literal">NULL</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span></span>&#123;</div><div class="line"></div><div class="line">    <span class="comment">//初始化锁</span></div><div class="line">    pthread_mutex_init(&amp;lockA, <span class="literal">NULL</span>);</div><div class="line">    pthread_mutex_init(&amp;lockB, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line">    <span class="keyword">pthread_t</span> tidA, tidB;</div><div class="line"></div><div class="line">    pthread_create(&amp;tidA, <span class="literal">NULL</span>, &amp;pthread_fun1, <span class="literal">NULL</span>);</div><div class="line">    pthread_create(&amp;tidB, <span class="literal">NULL</span>, &amp;pthread_fun2, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line">    pthread_join(tidA, <span class="literal">NULL</span>);</div><div class="line">    pthread_join(tidB, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line">    <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure>

<h3 id="实例三（读写锁）"><a href="#实例三（读写锁）" class="headerlink" title="实例三（读写锁）"></a><a href="#实例三（读写锁）" title="实例三（读写锁）"></a>实例三（读写锁）</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;pthread.h&gt;</span></span></div><div class="line"></div><div class="line"><span class="comment">//定义一个全局计数器</span></div><div class="line"><span class="keyword">int</span> counter;</div><div class="line"><span class="comment">//创建一个读写锁</span></div><div class="line"><span class="keyword">pthread_rwlock_t</span> rwlock;</div><div class="line"></div><div class="line"><span class="comment">//3个写线程，不定时写同一全局资源</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">th_write</span><span class="params">(<span class="keyword">void</span> </span></em> argv)</span>&#123;</div><div class="line">    <span class="keyword">int</span> t;</div><div class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</div><div class="line">        usleep(<span class="number">100</span>);</div><div class="line">        pthread_rwlock_wrlock(&amp;rwlock);</div><div class="line">        t = counter;</div><div class="line">        usleep(<span class="number">100</span>);</div><div class="line">        <span class="built_in">printf</span>(<span class="string">“write %x counter=%d ++counter=%d\n”</span>, pthread_self(), t, ++counter);</div><div class="line">        pthread_rwlock_unlock(&amp;rwlock);</div><div class="line">        usleep(<span class="number">100</span>);</div><div class="line">    &#125;</div><div class="line"></div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">//5个读线程，不定时读同一全局资源</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">th_read</span><span class="params">(<span class="keyword">void</span> </span></em> argv)</span>&#123;</div><div class="line"></div><div class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</div><div class="line">        pthread_rwlock_rdlock(&amp;rwlock);</div><div class="line">        <span class="built_in">printf</span>(<span class="string">“read %x counter=%d\n”</span>, pthread_self(), counter);</div><div class="line">        pthread_rwlock_unlock(&amp;rwlock);</div><div class="line">        usleep(<span class="number">100</span>);</div><div class="line">    &#125;</div><div class="line"></div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">//创建3个写线程，5个读线程</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</div><div class="line">    <span class="keyword">pthread_t</span> tid[<span class="number">8</span>];</div><div class="line">    <span class="comment">//初始化读写锁</span></div><div class="line">    pthread_rwlock_init(&amp;rwlock, <span class="literal">NULL</span>);</div><div class="line">    <span class="keyword">int</span> i;</div><div class="line">    <span class="comment">//创建3个写线程</span></div><div class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; <span class="number">3</span>; i++)&#123;</div><div class="line">        pthread_create(&amp;tid[i], <span class="literal">NULL</span>, th_write, <span class="literal">NULL</span>);</div><div class="line">    &#125;</div><div class="line">    <span class="comment">//创建5个读线程</span></div><div class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; <span class="number">5</span>; i++)&#123;</div><div class="line">        pthread_create(&amp;tid[i+<span class="number">3</span>], <span class="literal">NULL</span>, th_read, <span class="literal">NULL</span>);</div><div class="line">    &#125;</div><div class="line">    <span class="comment">//销毁读写锁</span></div><div class="line">    pthread_rwlock_destroy(&amp;rwlock);</div><div class="line"></div><div class="line">    <span class="comment">//回收线程资源</span></div><div class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; <span class="number">8</span>; i++)&#123;</div><div class="line">        pthread_join(tid[i], <span class="literal">NULL</span>);</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure>

<h3 id="实例四（条件变量）"><a href="#实例四（条件变量）" class="headerlink" title="实例四（条件变量）"></a><a href="#实例四（条件变量）" title="实例四（条件变量）"></a>实例四（条件变量）</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;pthread.h&gt;</span></span></div><div class="line"></div><div class="line"><span class="comment">//定义一个互斥锁</span></div><div class="line"><span class="keyword">pthread_mutex_t</span> lock;</div><div class="line"><span class="comment">//定义一个条件变量</span></div><div class="line"><span class="keyword">pthread_cond_t</span> cond;</div><div class="line"></div><div class="line"><span class="comment">//定义一个链表结构体（多线程操作的全局资源）</span></div><div class="line"><span class="keyword">struct</span> msg&#123;</div><div class="line">    <span class="keyword">struct</span> msg<em> next;   <span class="comment">//指针域</span></em></div><div class="line">    <span class="keyword">int</span> num;            <span class="comment">//数据域</span></div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="comment">//链表头</span></div><div class="line"><span class="keyword">struct</span> msg head;</div><div class="line"></div><div class="line"><span class="comment">//生产者</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">producer</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>&#123;</div><div class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</div><div class="line">        <span class="comment">//获取锁</span></div><div class="line">        pthread_mutex_lock(&amp;lock);</div><div class="line"></div><div class="line">        <span class="comment">//生产商品 (此处部分代码可放在获取锁之前执行，进行优化。为了看着直观所以代码都写在临界区了)</span></div><div class="line">        <span class="keyword">struct</span> msg <em>mp = <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(<span class="keyword">struct</span> msg));</em></div><div class="line">        mp-&gt;next = head;</div><div class="line">        mp-&gt;num = rand() % <span class="number">1000</span> + <span class="number">1</span>;</div><div class="line">        head = mp;</div><div class="line">        <span class="built_in">printf</span>(<span class="string">“Produce %d\n”</span>, mp-&gt;num);</div><div class="line"></div><div class="line">        <span class="comment">//释放锁</span></div><div class="line">        pthread_mutex_unlock(&amp;lock);</div><div class="line"></div><div class="line">        <span class="comment">//通知其中一个线程（停留在pthread_cond_wait的线程）</span></div><div class="line">        pthread_cond_signal(&amp;cond);</div><div class="line"></div><div class="line">        <span class="comment">//随机停留几秒，方便观察</span></div><div class="line">        sleep(rand() % <span class="number">3</span>);</div><div class="line">    &#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">//消费者</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">consumer</span><span class="params">(<span class="keyword">void</span><em> argv)</em></span></span>&#123;</div><div class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</div><div class="line">        <span class="comment">//获取锁</span></div><div class="line">        pthread_mutex_lock(&amp;lock);</div><div class="line">        <span class="keyword">while</span>(head == <span class="literal">NULL</span>)&#123;</div><div class="line">            <span class="comment">//等待条件成立</span></div><div class="line">            pthread_cond_wait(&amp;cond, &amp;lock);</div><div class="line">            <span class="built_in">printf</span>(<span class="string">“pthread_cond_wait\n”</span>);</div><div class="line">        &#125;</div><div class="line"></div><div class="line">        <span class="comment">//消费产品</span></div><div class="line">        <span class="keyword">struct</span> msg mp = head;</div><div class="line">        head = mp-&gt;next;</div><div class="line">        <span class="built_in">printf</span>(<span class="string">“Consume %d\n”</span>, mp-&gt;num);</div><div class="line">        <span class="built_in">free</span>(mp);</div><div class="line"></div><div class="line">        <span class="comment">//释放锁</span></div><div class="line">        pthread_mutex_unlock(&amp;lock);</div><div class="line">        sleep(rand() % <span class="number">3</span>);</div><div class="line">    &#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">//使用条件变量(thread_cond_t）实现生产者消费者模型</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</div><div class="line"></div><div class="line">    <span class="comment">//初始化互斥锁</span></div><div class="line">    pthread_mutex_init(&amp;lock, <span class="literal">NULL</span>);</div><div class="line">    <span class="comment">//初始化条件变量</span></div><div class="line">    pthread_cond_init(&amp;cond, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line">    <span class="keyword">pthread_t</span> pid, cid;</div><div class="line">    <span class="comment">//创建生产者线程</span></div><div class="line">    pthread_create(&amp;pid, <span class="literal">NULL</span>, producer, <span class="literal">NULL</span>);</div><div class="line">    <span class="comment">//创建消费者线程</span></div><div class="line">    pthread_create(&amp;cid, <span class="literal">NULL</span>, consumer, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line">    <span class="comment">//回收线程</span></div><div class="line">    pthread_join(pid, <span class="literal">NULL</span>);</div><div class="line">    pthread_join(cid, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line">    <span class="comment">//销毁锁</span></div><div class="line">    pthread_mutex_destroy(&amp;lock);</div><div class="line">    <span class="comment">//销毁条件变量</span></div><div class="line">    pthread_cond_destroy(&amp;cond);</div><div class="line"></div><div class="line">    <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure>

<h3 id="实例五（信号量）"><a href="#实例五（信号量）" class="headerlink" title="实例五（信号量）"></a><a href="#实例五（信号量）" title="实例五（信号量）"></a>实例五（信号量）</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;pthread.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;semaphore.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> NUM 5</span></div><div class="line"></div><div class="line"><span class="comment">//全局资源</span></div><div class="line"><span class="keyword">int</span> <span class="built_in">queue</span>[NUM];</div><div class="line"><span class="comment">//定义两个信号量</span></div><div class="line"><span class="comment">//blank_number 表示队列空闲数量</span></div><div class="line"><span class="comment">//product_number 表示队列使用数量</span></div><div class="line"><span class="keyword">sem_t</span> blank_number, product_number;</div><div class="line"></div><div class="line"><span class="comment">//生产者</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">producer</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>&#123;</div><div class="line">    <span class="keyword">int</span> i = <span class="number">0</span>;</div><div class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</div><div class="line">    </div><div class="line">        <span class="comment">//如果blank_number为0，阻塞等待，调用成功后，blank_number-1</span></div><div class="line">        sem_wait(&amp;blank_number);</div><div class="line">        <span class="built_in">queue</span>[i] = rand() % <span class="number">1000</span> + <span class="number">1</span>;<span class="comment">//生产商品</span></div><div class="line">        <span class="built_in">printf</span>(<span class="string">“produce %d\n”</span>, <span class="built_in">queue</span>[i]);</div><div class="line">        <span class="comment">//调用成功后，product_number+1,表示仓库生产了一件商品，product_number&gt;0 消费者开始消费产品。</span></div><div class="line">        sem_post(&amp;product_number);</div><div class="line">        i = (i + <span class="number">1</span>) % NUM;</div><div class="line"></div><div class="line">        <span class="comment">//usleep(rand() % 3000);</span></div><div class="line">    &#125;   </div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">//消费者</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">consumer</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>&#123;</div><div class="line">    <span class="keyword">int</span> i = <span class="number">0</span>;</div><div class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</div><div class="line">        <span class="comment">//如果product_number为0，阻塞等待，调用成功后，product_number-1</span></div><div class="line">        sem_wait(&amp;product_number);</div><div class="line">        <span class="comment">//消费产品</span></div><div class="line">        <span class="built_in">printf</span>(<span class="string">“Consume %d\n”</span>, <span class="built_in">queue</span>[i]);</div><div class="line">        <span class="built_in">queue</span>[i] = <span class="number">0</span>;</div><div class="line">        <span class="comment">//调用成功后，blank_number+1,表示仓库消费了一件商品，blank_number&gt;0 生成这开始生产产品</span></div><div class="line">        sem_post(&amp;blank_number);</div><div class="line">        i = (i + <span class="number">1</span>) % NUM;</div><div class="line"></div><div class="line">        sleep(rand()%<span class="number">5</span>);</div><div class="line">    &#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">//使用信号量同步线程</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</div><div class="line"></div><div class="line">    <span class="keyword">pthread_t</span> pid, cid;</div><div class="line"></div><div class="line">    <span class="comment">//初始化信号量</span></div><div class="line">    sem_init(&amp;blank_number, <span class="number">0</span>, NUM);</div><div class="line">    sem_init(&amp;product_number, <span class="number">0</span>, <span class="number">0</span>);</div><div class="line"></div><div class="line">    <span class="comment">//创建线程</span></div><div class="line">    pthread_create(&amp;pid, <span class="literal">NULL</span>, producer, <span class="literal">NULL</span>);</div><div class="line">    pthread_create(&amp;cid, <span class="literal">NULL</span>, consumer, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line">    <span class="comment">//回收线程资源</span></div><div class="line">    pthread_join(pid, <span class="literal">NULL</span>);</div><div class="line">    pthread_join(cid, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line">    <span class="comment">//销毁信号量</span></div><div class="line">    sem_destroy(&amp;blank_number);</div><div class="line">    sem_destroy(&amp;product_number);</div><div class="line"></div><div class="line">    <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/计算机/" rel="tag"># 计算机</a>
          
            <a href="/tags/pthread/" rel="tag"># pthread</a>
          
            <a href="/tags/线程同步/" rel="tag"># 线程同步</a>
          
            <a href="/tags/互斥量/" rel="tag"># 互斥量</a>
          
            <a href="/tags/读写锁/" rel="tag"># 读写锁</a>
          
            <a href="/tags/条件变量/" rel="tag"># 条件变量</a>
          
            <a href="/tags/信号量/" rel="tag"># 信号量</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2016/11/22/nginx反向代理与负载均衡/" rel="next" title="nginx反向代理与负载均衡">
                <i class="fa fa-chevron-left"></i> nginx反向代理与负载均衡
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2016/11/22/C线程/" rel="prev" title="C线程">
                C线程 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          
            <img class="site-author-image" itemprop="image"
              src="/uploads/avatar.jpg"
              alt="eregg" />
          
            <p class="site-author-name" itemprop="name">eregg</p>
            <p class="site-description motion-element" itemprop="description">青，取之于蓝，而青于蓝</p>
        </div>

        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
            
              <a href="/archives/">
            
                <span class="site-state-item-count">10</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          

          
            
            
            <div class="site-state-item site-state-tags">
              <a href="/tags/index.html">
                <span class="site-state-item-count">31</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        
          <div class="feed-link motion-element">
            <a href="/atom.xml" rel="alternate">
              <i class="fa fa-rss"></i>
              RSS
            </a>
          </div>
        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/eregg" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i>GitHub</a>
              </span>
            
              <span class="links-of-author-item">
                <a href="mailto:ereggmail@163.com" target="_blank" title="E-Mail">
                  
                    <i class="fa fa-fw fa-envelope"></i>E-Mail</a>
              </span>
            
          
        </div>

        
        

        
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#线程为什么要同步"><span class="nav-number">1.</span> <span class="nav-text">线程为什么要同步</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#互斥量"><span class="nav-number">2.</span> <span class="nav-text">互斥量</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#临界区（Critical-Section）"><span class="nav-number">2.1.</span> <span class="nav-text">临界区（Critical Section）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#临界区的选定"><span class="nav-number">2.2.</span> <span class="nav-text">临界区的选定</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#互斥量（mutex）原语"><span class="nav-number">2.3.</span> <span class="nav-text">互斥量（mutex）原语</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#pthread-mutex-t"><span class="nav-number">2.3.1.</span> <span class="nav-text">pthread_mutex_t</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#pthread-mutex-init"><span class="nav-number">2.3.2.</span> <span class="nav-text">pthread_mutex_init</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#pthread-mutex-lock"><span class="nav-number">2.3.3.</span> <span class="nav-text">pthread_mutex_lock</span></a></li></ol></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实例二（死锁）"><span class="nav-number">3.</span> <span class="nav-text">实例二（死锁）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实例三（读写锁）"><span class="nav-number">4.</span> <span class="nav-text">实例三（读写锁）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实例四（条件变量）"><span class="nav-number">5.</span> <span class="nav-text">实例四（条件变量）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实例五（信号量）"><span class="nav-number">6.</span> <span class="nav-text">实例五（信号量）</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy;  2015 &mdash; 
  <span itemprop="copyrightYear">2017</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">eregg</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动</div>

  <span class="post-meta-divider">|</span>

  <div class="theme-info">主题 &mdash; <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">NexT.Mist</a> v5.1.2</div>


        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>

  
  <script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.2"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.2"></script>



  
  

  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.2"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.2"></script>


  

  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.2"></script>



  


  




	





  





  








  





  

  

  

  

  

  

</body>
</html>
